package com.ruoyi.iot.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.ruoyi.iot.constant.DbDataTypeEnum;
import com.ruoyi.iot.constant.MateConstant;
import com.ruoyi.iot.domain.*;
import com.ruoyi.iot.domain.data.FieldRunData;
import com.ruoyi.iot.service.*;
import com.ruoyi.iot.util.DianJHttpUtil;
import com.ruoyi.iot.util.HnHttpUtils;
import com.ruoyi.iot.util.HttpTokenUtil;
import com.ruoyi.iot.util.NtsHttpUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class FacDevicesDataServiceImpl implements IFacDevicesDataService {
    @Autowired
    IFacDevicesJobService facDevicesJobService;

    @Autowired
    IFacDeviceBasicService facDeviceBasicService;

    @Autowired
    IFacDevicesTypeService facDevicesTypeService;

    @Autowired
    IFacDevicesMonitorService facDevicesMonitorService;

    @Autowired
    IFacDevicesRundataService facDevicesRunDataService;

    @Autowired
    IFacDevicesMonitorParamService facDevicesMonitorParamService;

    @Autowired
    DbService dbService;
    @Override
    public void syncLastData() {
        FacDevicesJob param=new  FacDevicesJob();
        param.setIsOpen(true);
        List<FacDevicesJob> list=facDevicesJobService.selectFacDevicesJobList(param);
        for(FacDevicesJob job:list){
            String className=job.getJobClass();
            String mothName=job.getJobMethod();
            if(ObjectUtil.isNotEmpty(className)) {
                try{
                    Class c = (Class) Class.forName(className);
                    Method method=c.getMethod(mothName, DeviceDataRequest.class);
                    DeviceDataRequest request=new DeviceDataRequest();
                    Long deviceId= job.getDeviceId();
                    request.setDeviceId(deviceId);
                    Object o= SpringUtil.getBean(c);
                    method.invoke(o,request);
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        }
    }

    /**
     * 获取设备最新数据（httpUrl,deviceId） (河南获取最新数据）
     * @param deviceDataRequest
     */
    @Override
    public void syncSoilWLastData(DeviceDataRequest deviceDataRequest) {
        Long deviceId=deviceDataRequest.getDeviceId();
        FacDeviceBasic deviceEntity=facDeviceBasicService.selectFacDeviceBasicById(deviceId);
        if(ObjectUtil.isNotEmpty(deviceEntity)){
            //根据设备型号
            FacDevicesType typeEntity=new FacDevicesType();
            typeEntity.setCode(deviceEntity.getTypeCode());
            List<FacDevicesType> typeList= facDevicesTypeService.selectFacDevicesTypeList(typeEntity);
            if(ObjectUtil.isNotEmpty(typeList) && typeList.size()>0) {
                FacDevicesType currType = typeList.get(0);
                //根据型号获取监测类型
                FacDevicesMonitor queryEntity=new  FacDevicesMonitor();
                queryEntity.setTypeId(currType.getId());
                List<FacDevicesMonitor> monitorList= facDevicesMonitorService.selectFacDevicesMonitorList(queryEntity);
                if(ObjectUtil.isNotEmpty(monitorList) && monitorList.size()>0){
                    FacDevicesMonitor currMonitor=monitorList.get(0);
                    //根据设备获取对接数据
                    FacDevicesRundata runDataQuery=new  FacDevicesRundata();
                    runDataQuery.setDeviceId( deviceEntity.getId());
                    List<FacDevicesRundata> runDataList=facDevicesRunDataService.selectFacDevicesRundataList(runDataQuery);
                    if(runDataList.size()>0){
                        //根据对接信息获取数据
                        List<FieldRunData> list= new ArrayList<>();
                        list= HnHttpUtils.getData(runDataList.get(0).getuUrl(),deviceEntity.getDeviceSn());
                        //根据监测类型获取监测字段
                        saveDataByList(deviceEntity,currMonitor,runDataList.get(0),list);
                    }
                }
            }
        }
    }

    /**获取设备Token  点将科技土壤**/
    @Override
    public void syncGetToken(DeviceDataRequest deviceDataRequest) {
        Long deviceId=deviceDataRequest.getDeviceId();
        FacDeviceBasic deviceEntity=facDeviceBasicService.selectFacDeviceBasicById(deviceId);
        if(ObjectUtil.isNotEmpty(deviceEntity)){
            //获取运行数据
            FacDevicesRundata runDataQuery=new  FacDevicesRundata();
            runDataQuery.setDeviceId( deviceEntity.getId());
            List<FacDevicesRundata> runDataList=facDevicesRunDataService.selectFacDevicesRundataList(runDataQuery);
            if(runDataList.size()>0){
                FacDevicesRundata cRunData=runDataList.get(0);
                String cToken= HttpTokenUtil.getDianJToken(cRunData.getuName(),cRunData.getuPassword());
                if(ObjectUtil.isNotEmpty((cToken))){
                        deviceDataRequest.setToken(cToken);
                        syncHttpLastData(deviceDataRequest);
                }
            }
        }
    }
    /**获取设备最新数据（httpUrl,token,deviceSn)**/
    @Override
    public void syncHttpLastData(DeviceDataRequest deviceDataRequest){
        //获取带有Token的最新数据
        Long deviceId=deviceDataRequest.getDeviceId();
        FacDeviceBasic deviceEntity=facDeviceBasicService.selectFacDeviceBasicById(deviceId);
        if(ObjectUtil.isNotEmpty(deviceEntity)){
            //根据设备型号
            FacDevicesType typeEntity=new FacDevicesType();
            typeEntity.setCode(deviceEntity.getTypeCode());
            List<FacDevicesType> typeList= facDevicesTypeService.selectFacDevicesTypeList(typeEntity);
            if(ObjectUtil.isNotEmpty(typeList) && typeList.size()>0) {
                FacDevicesType currType = typeList.get(0);
                //根据型号获取监测类型
                FacDevicesMonitor queryEntity=new  FacDevicesMonitor();
                queryEntity.setTypeId(currType.getId());
                List<FacDevicesMonitor> monitorList= facDevicesMonitorService.selectFacDevicesMonitorList(queryEntity);
                if(ObjectUtil.isNotEmpty(monitorList) && monitorList.size()>0){
                    FacDevicesMonitor currMonitor=monitorList.get(0);
                    //根据设备获取对接数据
                    FacDevicesRundata runDataQuery=new  FacDevicesRundata();
                    runDataQuery.setDeviceId( deviceEntity.getId());
                    List<FacDevicesRundata> runDataList=facDevicesRunDataService.selectFacDevicesRundataList(runDataQuery);
                    if(runDataList.size()>0){
                        //根据对接信息获取数据
                        List<FieldRunData> list= new ArrayList<>();
                        //根据型号区分调用的最新数据
                        list= DianJHttpUtil.getData(runDataList.get(0).getuUrl(),deviceEntity.getDeviceSn(),deviceDataRequest.getToken());
                        //根据监测类型获取监测字段
                        saveDataByList(deviceEntity,currMonitor,runDataList.get(0),list);
                    }
                }
            }
        }
    }

    /**获取最新数据 - 南土所**/
    @Override
    public void syncGetNTSLastData(DeviceDataRequest deviceDataRequest){
        Long deviceId=deviceDataRequest.getDeviceId();
        FacDeviceBasic deviceEntity=facDeviceBasicService.selectFacDeviceBasicById(deviceId);
        if(ObjectUtil.isNotEmpty(deviceEntity)){
            FacDevicesType typeEntity=new FacDevicesType();
            typeEntity.setCode(deviceEntity.getTypeCode());
            List<FacDevicesType> typeList= facDevicesTypeService.selectFacDevicesTypeList(typeEntity);
            if(ObjectUtil.isNotEmpty(typeList) && typeList.size()>0) {
                FacDevicesType currType = typeList.get(0);
                //根据型号获取监测类型
                FacDevicesMonitor queryEntity=new  FacDevicesMonitor();
                queryEntity.setTypeId(currType.getId());
                List<FacDevicesMonitor> monitorList= facDevicesMonitorService.selectFacDevicesMonitorList(queryEntity);
                if(ObjectUtil.isNotEmpty(monitorList) && monitorList.size()>0){
                    FacDevicesMonitor currMonitor=monitorList.get(0);
                    //根据设备获取对接数据
                    FacDevicesRundata runDataQuery=new  FacDevicesRundata();
                    runDataQuery.setDeviceId( deviceEntity.getId());
                    List<FacDevicesRundata> runDataList=facDevicesRunDataService.selectFacDevicesRundataList(runDataQuery);
                    if(runDataList.size()>0){
                        //根据对接信息获取数据
                        List<FieldRunData> list= new ArrayList<>();
                        list= NtsHttpUtils.getData(runDataList.get(0).getuUrl(),deviceEntity.getDeviceSn(),runDataList.get(0).getuToken());
                        //根据监测类型获取监测字段
                        saveDataByList(deviceEntity,currMonitor,runDataList.get(0),list);
                    }
                }
            }
        }
    }

    @Override
    public void saveDataByList(FacDeviceBasic device, FacDevicesMonitor monitorVo, FacDevicesRundata rundata, List<FieldRunData> list) {
        String deviceCode=device.getDeviceSn();
        //根据型号监控类型获取监控字段
        FacDevicesMonitorParam queryEntity=new  FacDevicesMonitorParam();
        queryEntity.setMonitorId(monitorVo.getId());
        List<FacDevicesMonitorParam> paramList=facDevicesMonitorParamService.selectFacDevicesMonitorParamList(queryEntity);
        //判断是否有固定字段
        String ficFiels="";
        for (FacDevicesMonitorParam param: paramList) {
            if(MateConstant.YES.equals(param.getIsFix())){
                ficFiels=param.getField();
                break;
            }
        }
        //根据类型判断是字段存储还是表存储
        if(MateConstant.DATA_FIELD.equals(monitorVo.getDataClass())) {
//            saveFielData(device, monitorVo, rundata, list);
        }
        else{
            if(ObjectUtil.isEmpty(list)){
                return;
            }
            if(ObjectUtil.isNotEmpty(ficFiels)) {
                Map<String, List<FieldRunData>> scopeList = list.stream().filter(a->ObjectUtil.isNotNull(a.getMonitoringScope())).collect(Collectors.groupingBy(FieldRunData::getMonitoringScope));
                for (String scope : scopeList.keySet()) {
                    HashMap data=new HashMap(5);
                    for(FieldRunData dd:scopeList.get(scope)){
                        data.put(dd.getField(),dd.getFieldValue());
                        data.put("monitoring_time",dd.getMonitoringTime());
                    }
                    data.put(ficFiels,scope);
                    saveTableData(device, monitorVo, rundata,data,paramList);
                }
            }
            else{
                HashMap data=new HashMap(5);
                for(FieldRunData dd: list){
                    data.put(dd.getField(),dd.getFieldValue());
                    data.put("monitoring_time",dd.getMonitoringTime());
                }
                saveTableData(device, monitorVo, rundata,data,paramList);
            }
        }

    }

    /**表数据存储**/
    private void saveTableData(FacDeviceBasic device, FacDevicesMonitor monitorVo, FacDevicesRundata rundata, HashMap data,List<FacDevicesMonitorParam> params) {
        String ficFiels="";
        for (FacDevicesMonitorParam param:params) {
            if(MateConstant.YES.equals(param.getIsFix())){
                ficFiels=param.getField();
                break;
            }
        }
        LocalDateTime now =(LocalDateTime) data.get("monitoring_time");
        //判断同一时间的数据是否已入库
        String tablename=monitorVo.getTableName();
        String sql = "select count(1) from \"" + tablename + "\" where device_id=" +device.getId()
                + " and monitoring_time=timestamp '"+ LocalDateTimeUtil.format(now, DatePattern.NORM_DATETIME_MS_PATTERN)+"'"
                +(ObjectUtil.isNotEmpty(ficFiels)?(" and "+ficFiels+"='"+data.get(ficFiels)+"'"):"");
        int num = dbService.count(sql);
        if(num==0){
            HashMap<String, Object> kv = new HashMap<>(30);
            Long dataId= IdUtil.getSnowflake().nextId();
            kv.put("id",dataId);
            kv.put("device_id", device.getId());
            kv.put("monitoring_time",now);
            for (FacDevicesMonitorParam param:params) {
                String key = param.getField();
                if(DbDataTypeEnum.IMAGES.getCode().equals(param.getFieldType())){
//                    try {
//                        if (ObjectUtils.isNotEmpty(data.get(key))) {
//                            Object obj=data.get(key);
//                            if(obj instanceof String) {
//                                String img = (String)obj;
//                                if(StrUtil.containsAny(img,".","//")) {
//                                    String imgid = saveImage(device.getDeviceSn(), LocalDateTimeUtil.format(now, DatePattern.NORM_DATETIME_PATTERN),dataId, img, PinyinUtil.getFirstLetter(param.getFieldName(), ""));
//                                    kv.put(key, imgid);
//                                }else{
//                                    kv.put(key, img);
//                                }
//                            }else{
//                                MultipartFile img = (MultipartFile)obj;
//                                String imgid = saveImage(device.getDeviceSn(), LocalDateTimeUtil.format(now, DatePattern.NORM_DATETIME_PATTERN)
//                                        , dataId, img, PinyinUtil.getFirstLetter(param.getFieldName(), ""));
//                                kv.put(key, imgid);
//                            }
//                        }
//                    }catch (Exception e){
//                        e.printStackTrace();
//                        kv.put(key, "");
//                    }
                }else if(DbDataTypeEnum.GEOM.getCode().equals(param.getFieldType())){
//                    kv.put("geom","st_geomfromgeojson('"+data.get(key)+"')");
//                    Geometry geom=GeomteryUtil.getGeometryFromGeojson((String) data.get(key));
//                    if(ObjectUtil.equals(geom.getCentroid().getX(),0)){
//                        device.setGeom((String) data.get(key));
//                    }
                } else{
                    kv.put(key, data.get(key));
                }
            }
            dbService.saveTable(tablename, kv);
            //修改基础表在线状态，最新数据时间
            //存储子项数据

        }
    }
    /**字段数据存储**/
}
